/**
 * [阶乘](https://en.wikipedia.org/wiki/Factorial)，通常写作 n!，是所有小于或等于 n 的正整数的乘积。
 * 阶乘通常以递归方式实现，但这种迭代方法显著更快且更简单。
 *
 * @param {number} n 输入，必须为大于或等于 1 的整数
 * @returns {number} 阶乘：n!
 * @throws {Error} 如果 n 小于 0 或不是整数
 * @example
 * factorial(5); // => 120
 */
function factorial(n) {
    // 阶乘在数学上对负数未定义
    if (n < 0) {
        throw new Error("阶乘需要非负值");
    }

    if (Math.floor(n) !== n) {
        throw new Error("阶乘需要整数输入");
    }

    // 通常你会从大到小展开阶乘函数，例如
    // 5! = 5 * 4 * 3 * 2 * 1。这里采用相反的方向，
    // 从 2 开始计数到目标数字，由于任何数乘以 1 都是其本身，
    // 因此循环只需从 2 开始。
    let accumulator = 1;
    for (let i = 2; i <= n; i++) {
        // 对于每个小于或等于 `n` 的数字，将累加器乘以该数字。
        accumulator *= i;
    }
    return accumulator;
}

export default factorial;
